/*
 * IMPORTANT NOTE:
 * It's inadvisable to run a coprocessor in the same thread as the
 * control processor, because of the recursive mutexes we use.
 * This means that we can't rely on the locking mechanisms that protect
 * variables, etc.
 */
 
#ifndef __SC_H_INCLUDED
#define __SC_H_INCLUDED

#include <scos.h>
#include "log.h"

#ifdef __cplusplus
extern "C" {
#endif

/* *** TO BE REMOVED *** */
#define SC_MAX_BUFFERS    32768
#define SC_MAX_OPERATIONS 4096
#define SC_MAX_ARGUMENTS  8
#define SC_MAX_STREAMS    4096

#define SC_BUF_SIZE       (1024*1024*24)

#define SC_VAR_STREAM    0
#define SC_VAR_INTEGER   1
#define SC_VAR_DOUBLE    2
#define SC_VAR_POINTER   3

/* For instrumented traces */
#define IF     0
#define SWITCH 1
#define LOOP   2

typedef int STREAM;

typedef struct stream_s
{
  void *address;
  int buffer, multi;
} stream_t;

void scInit(int argc, char **argv);
void scMapNextProcessor(void);

#define scOp0(format, op) _scOp(__LINE__, 0, format, op)
#define scOp1(format, op, a) _scOp(__LINE__, 0, format, op, a)
#define scOp2(format, op, a, b) _scOp(__LINE__, 0, format, op, a, b)
#define scOp3(format, op, a, b, c) _scOp(__LINE__, 0, format, op, a, b, c)
#define scOp4(format, op, a, b, c, d) _scOp(__LINE__, 0, format, op, a, b, c, d)
#define scOp5(format, op, a, b, c, d, e) _scOp(__LINE__, 0, format, op, a, b, c, d, e)
#define scOp6(format, op, a, b, c, d, e, f) _scOp(__LINE__, 0, format, op, a, b, c, d, e, f)
#define scOp7(format, op, a, b, c, d, e, f, g) _scOp(__LINE__, 0, format, op, a, b, c, d, e, f, g)

void * _scOp(int line, int parent, char *format, int op, ...);

#define scThread0(format, op) _scThread(#op, format, op)
#define scThread1(format, op, a) _scThread(#op, format, op, a)
#define scThread2(format, op, a, b) _scThread(#op, format, op, a, b)
#define scThread3(format, op, a, b, c) _scThread(#op, format, op, a, b, c)
#define scThread4(format, op, a, b, c, d) _scThread(#op, format, op, a, b, c, d)

#ifdef __cplusplus
void _scThread(char *format, char *text, void (*op)(...), ...);
#else
void _scThread(char *format, char *text, void (*op)(), ...);
#endif
void _finalize(STREAM *s);
void _block(void *address);
void _schedule(int make_it_run);
void _cycle(void *address);
void _multi(void *address);
void _allmulti(int multiuse);
void _mapto(int _affinity);
void _awaitall(void);
void _setbuffersize(int size);
int scExit(void);

int scTrace(int type, int line, int parent, int condition);

int    *scint(int i);
double *scdbl(double f);

#define READ 0
#define read(a, b) scOp2("dI", READ, a, b)

#define WRITE 1
#define write(a, b) scOp2("id", WRITE, a, b)

#define GENERATE 2
#define generate(a, b) scOp2("dI", GENERATE, a, b)

#define DISCARD 3
#define discard(a) scOp1("i", DISCARD, a)

#define DISPLAY 4
#define display(a) scOp1("i", DISPLAY, a)

#define CAPTURE 5
#define capture(a) scOp1("I", CAPTURE, a)

#define TRANSPORT 6
#define LOAD      7
#define CYCLE     8

#define GENSIZE   9


#ifdef __cplusplus
}
#endif

#endif /* __SC_H_INCLUDED */
